home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright © 1991-1995 by TopSoft Inc. All rights reserved.
-
- You may distribute this file under the terms of the TopSoft
- Artistic License, accompanying this package.
-
- This file was developed by George (ty) Tempel in connection with TopSoft, Inc..
- See the Modification History for more details.
-
- This file is based upon code developed by Bryan K. Ressler (Beaker)
- of Apple DTS as a replacement for TextBox
-
- Product
- About Box
-
- FILE
- ABUTextBox.c
-
- NAME
- ABUTextBox.c, part of the ABox project source code,
- responsible for mix-in handling the AboutBox textbox stuff.
-
- DESCRIPTION
- This file contains defines for the about box modules.
-
- DEVELOPED BY
- George (ty) Tempel netromancr@aol.com
- All code in this file, and its associated header file was
- Created by George (ty) Tempel in connection with the TopSoft, Inc.
- "FilterTop" application development, except where noted.
-
- This file is based upon code developed by Bryan K. Ressler (Beaker)
- of Apple DTS as a replacement for TextBox
-
-
- CARETAKER - George (ty) Tempel <netromancr@aol.com>
- Please consult this person for any changes or suggestions to this file.
-
- MODIFICATION HISTORY
-
- dd mmm yy - xxx - patchxx: description of patch
- 10 June 94 - ty - Initial Version Created
- 20-july-94 - ty - initial version released
- 23-may-95 - ty - changes for compatibility with the CodeWarrior CW6
- release and the associated Universal Headers from Apple:
- most methods that returned references now have "Ref" at
- the end of their methods names to prevent possible collisions
- with datatypes and classes of the same name (older versions
- of the compiler didn't have a problem with this).
-
- */
-
- /*===========================================================================*/
-
- /*======= Segmentation directives ========*/
-
- #ifdef USE_MANUAL_SEGMENTATION
- #pragma segment ty
- #endif
-
- /*============ Header files ==============*/
-
- #include "ABUTextBox.h"
-
- /*=============== Globals ================*/
-
-
- /*================ CODE ==================*/
-
-
- /*=============================== ABUTextBox::ABUTextBox ================================*/
- ABUTextBox::ABUTextBox(void)
- {
- } // end ABUTextBox
-
-
- /*=============================== ABUTextBox::~ABUTextBox ================================*/
- ABUTextBox::~ABUTextBox(void)
- {
- } // end ~ABUTextBox
-
-
-
-
-
-
-
-
- /*=============================== ABUTextBox::NTBLineHeight ==================================*/
- //
- // NTBLineHeight - figures line height
- //
- // Input: theText the entire text that was given to the NeoTextBox call
- // textLen the length in bytes of the text
- // lhCode the line height code that was passed to NeoTextBox
- // startY VAR - we return the starting vertical pen location here
- //
- // Output: returns the line height to use
- //
- //
- unsigned short ABUTextBox::NTBLineHeight(unsigned char *theText,
- unsigned long textLen,
- Rect *wrapBox,
- short lhCode,
- short *startY)
- {
- short asc,desc; /* Used in the OutlineMetrics calls */
- FontInfo fInfo; /* The old-style font information record */
- Point frac; /* The fraction for the TrueType calls */
- unsigned short lineHeight = 0; /* The return value */
- OSErr error;
-
- // begin here...
-
- if (!(theText && wrapBox))
- return lineHeight;
-
- ::GetFontInfo(&fInfo);
- if (lhCode < 0) {
-
- /*
- If the user has specified variable-height lines, we need to try
- to determine the tallest ascent in the given text. We can only
- really do this if the font is a TrueType font. Otherwise, we
- punt and use old-fashioned GetFontInfo numbers.
- */
-
- frac.h = frac.v = 1;
- if (gHasTrueType && IsOutline(frac, frac)) {
-
- /*
- At this point we know the current font is a TrueType font, so
- we do an OutlineMetrics call with our full text. It will put
- the tallest character ascent into asc, and the deepest descent
- into desc. Then we choose between whichever's most between
- the old-style ascent/descent and the numbers we get from
- the OutlineMetrics call.
- */
-
- error = OutlineMetrics((short) textLen, theText, frac, frac, &asc, &desc,
- nil, nil, nil);
- if (error)
- return lineHeight;
-
- lineHeight = MAXOF(fInfo.ascent, asc) + MAXOF(fInfo. descent,-desc) +
- fInfo.leading;
- *startY = wrapBox->top + MAXOF(fInfo.ascent, asc);
- *startY += fInfo.leading;
-
- } else {
-
- /*
- At this point we know the current font isn't TrueType, so we
- just use the old way of calculating line height.
- */
-
- lineHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
- *startY = wrapBox->top + fInfo.ascent + fInfo.leading;
- }
-
- } else if (lhCode == 0) {
-
- /*
- If the user has specified "default" line height, he just wants us
- to get the line height from the FontInfo record.
- */
-
- lineHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
- *startY = wrapBox->top + fInfo.ascent + fInfo.leading;
-
- } else {
-
- /* If the user has provided a specific line height, we just trust
- them. We can't really generate too good of a starting vertical
- coordinate, but we munge one together anyway.
- */
-
- lineHeight = lhCode;
- *startY = wrapBox->top + lhCode + fInfo.leading;
-
- }
-
- return(lineHeight);
- }
-
- /*=============================== ABUTextBox::NTBDraw ==================================*/
- //
- //
- // NTBDraw - draws a line with appropriate justification
- //
- // Input: breakCode the break code that was returned from StyledLineBreak
- // lineStart pointer to the beginning of the text for the current line
- // lineBytes the length in bytes of the the text for this line
- // wrapBox the box within which we're wrapping
- // align the text alignment as specified by the user
- // curY our current vertical pen coordinate
- // boxWidth the width of wrapBox (since NeoTextBox already calculated it)
- //
- // Output: none (draws on the screen)
- //
- //
- void ABUTextBox::NTBDraw(StyledLineBreakCode breakCode,
- unsigned char *lineStart,
- long lineBytes,
- Rect *wrapBox,
- short align,
- short curY,
- short boxWidth)
- {
- unsigned long blackLen; /* Length of non-white characters */
- short slop; /* Number of pixels of slop for full just */
-
- /*
- The first thing we do here is determine the length of the "black" part
- of the current line. This excludes spaces, carriage returns, and other
- white stuff depending on the language. How do we know what to elim-
- inate? We DON'T! So we ask our friend the Script Manager to do it
- for us. VisibleLength returns the number of bytes that we should use
- for pixel width calculations.
- */
-
- if (!(lineStart && wrapBox))
- return;
-
- //pascal long VisibleLength(Ptr textPtr,long textLen)
- blackLen = ::VisibleLength((Ptr) lineStart, lineBytes);
-
- if (align == kNTBJustFull) {
-
- /*
- For full justification, we need to calculate the "slop" space on
- the line that's not filled up by the text. Then we move to the
- margin and get ready to draw BUT WAIT! If this is the last line of
- a paragraph, we need to draw it with whatever the system justifi-
- cation is. So if the break code indicates we're at the end of the
- text, or we can find a carriage return there ourselves, we just
- change the text alignment to the current default system text align-
- ment and fall through without drawing. If it's just another line
- within a paragraph, we use the handy Script Manager routine DrawJust
- to draw it justified. In languages like Arabic, full justification
- is performed differently than just spacing out the words. DrawJust
- handles cases like these correctly.
-
- Note that when we go looking for the carriage return at the end of
- the line, it's okay to simply index to the last byte of the string.
- This is because the carriage return character, 0x0d, is in the
- control-code range, which is defined to never be the low byte of a
- two byte character.
- */
-
- slop = boxWidth - ::TextWidth(lineStart, 0, blackLen);
- ::MoveTo(wrapBox->left, curY);
- if (breakCode == smBreakOverflow ||
- *(lineStart + (lineBytes - 1)) == kNTBReturnChar)
- align = ::GetSysJust();
- else
- ::DrawJust((Ptr) lineStart, blackLen, slop);
- }
-
- /*
- For the rest of the text alignments (left, center, and right), we just
- move the pen to the right place and draw the text with DrawText. Note
- that the alignments that could have come into the NeoTextBox call have
- been resoved down to one of the four constants teForceLeft, teJustRight
- teJustCenter, or ntbJustFull.
- */
-
- switch(align) {
- case teForceLeft:
- case teJustLeft:
- ::MoveTo(wrapBox->left, curY);
- break;
- case teJustRight:
- ::MoveTo(wrapBox->right - ::TextWidth(lineStart, 0, blackLen), curY);
- break;
- case teJustCenter:
- ::MoveTo(wrapBox->left + (boxWidth - ::TextWidth(lineStart, 0, blackLen)) / 2,
- curY);
- break;
- }
- if (align != kNTBJustFull)
- ::DrawText(lineStart, 0, lineBytes);
- }
-
-
-
- /*=============================== ABUTextBox::DrawTextBox ==================================*/
- //
- // NeoTextBox - word-wraps text inside a given box
- //
- // Input: theText the text we need to wrap
- // textLen the length in bytes of the text
- // wrapBox the box within which we're wrapping
- // align the text alignment
- // teForceLeft, teFlushLeft left justified
- // teJustCenter, teCenter center justified
- // teJustRight, teFlushRight right justified
- // ntbJustFull full justified
- // teJustLeft, teFlushDefault system justified
- // lhCode the line height code that was passed to NeoTextBox
- // < 0 variable - based on tallest character
- // 0 default - based on GetFontInfo
- // > 0 fixed - use lhCode as the line height
- // endY VAR - if non-nil, the vertical coord of the last line
- // lhUsed VAR - if non-nil, the line height used to draw the text
- //
- // Output: returns the number of line drawn total (even if they drew outside of
- // the boundries of wrapBox)
- //
- //
- short ABUTextBox::DrawTextBox(unsigned char *theText, unsigned long textLen, Rect *wrapBox,
- short align, short lhCode, short *endY, short *lhUsed)
- {
- RgnHandle oldClip; /* Saved clipping region */
- StyledLineBreakCode breakCode; /* Returned code from StyledLineBreak */
- Fixed fixedMax; /* boxWidth converted to fixed point */
- Fixed wrapWid; /* Width to wrap to */
- short boxWidth; /* Width of the wrapBox */
- long lineBytes; /* Number of bytes in one line */
- unsigned short lineHeight; /* Calculated line height */
- short curY; /* Current vertical pen location */
- unsigned short lineCount = 0; /* Number of lines we've drawn */
- long textLeft; /* Pointer to remaining bytes of text */
- unsigned char *lineStart; /* Pointer to beginning of a line */
- unsigned char *textEnd; /* Pointer to the end of input text */
-
- // begin here...
- if (!(theText && wrapBox))
- return lineCount;
-
- /*
- First, we save the old clipping region and clip to wrapBox. Then, figure
- the width of wrapBox, and make a fixed point version of it. Also, resolve
- the text alignment teFlushDefault to be the default system text alignment.
- */
-
- ::GetClip((oldClip = ::NewRgn()));
- ::ClipRect(wrapBox);
- boxWidth = wrapBox->right - wrapBox->left;
- fixedMax = ::Long2Fix((long) boxWidth);
- if (align == teFlushDefault)
- align = GetSysJust();
-
- /*
- Now we call NTBLineHeight to calculate the appropriate line height. It
- also figures our starting vertical pen location in curY based on the
- line height and other metric parameters. Clear lineCount, set
- lineStart to point to the beginning of the text, calculate textEnd for
- comparison to know when we're done, and preset textLeft to be all the
- text.
- */
-
- lineHeight = ABUTextBox::NTBLineHeight(theText, textLen, wrapBox, lhCode, &curY);
- lineCount = 0;
- lineStart = theText;
- textEnd = theText + textLen;
- textLeft = textLen;
-
- /*
- This is the main wrap-and-draw loop. I bet you never thought wrapping
- text could be so easy...
- */
-
- do {
-
- /*
- Every line, we have to preset lineBytes to something non-zero.
- This tells StyledLineBreak that we're drawing the first format
- run on the line (of course, for us, there's only ONE format run
- total). Also preset wrapWid. StyledLineBreak will always modify
- lineBytes (to tell you how many bytes are on this line), and will
- modify wrapWid, so we have to reset them each line.
- */
-
- lineBytes = 1;
- wrapWid = fixedMax;
-
- breakCode = ::StyledLineBreak((Ptr) lineStart, textLeft, 0, textLeft, 0,
- &wrapWid, &lineBytes);
-
- /*
- Now that the Script Manager has done all the really hard work for
- us, we draw the line. We already knew lineStart, StyledLineBreak
- gave us lineBytes, which we pass to NTBDraw. It'll handle the
- different text alignments itself.
- */
-
- ABUTextBox::NTBDraw(breakCode, lineStart, lineBytes, wrapBox, align, curY, boxWidth);
-
- /*
- Now we advance our vertical position down by the height of one
- line, advance lineStart by the number of bytes we just drew,
- calculate a new textLeft, and increment our line count.
- */
-
- curY += lineHeight;
- lineStart += lineBytes;
- textLeft -= lineBytes;
- lineCount++;
-
- } while (lineStart < textEnd);
-
- /*
- Well that was a job well done. Let's return some useful values, too.
- If the user gave pointers for endY and lhUsed, we stuff our ending
- vertical coordinate and the line height we calculated into those,
- respectively. These allow the guy to put something after the wrapped
- text (or at least know the right place to put it).
- */
-
- if (endY)
- *endY = curY - lineHeight;
- if (lhUsed)
- *lhUsed = lineHeight;
-
- /*
- Finally, restore the clipping region, dispose of the region, and
- return the TOTAL number of lines drawn (note that we didn't stop
- drawing when curY advanced past wrapBox->bottom. This way, the user
- could tell that the text overflowed wrapBox. If you want to know how
- many lines fit, divide wrapBox by lhUsed. This way, you get the best
- of both worlds.
- */
-
- ::SetClip(oldClip);
- ::DisposeRgn(oldClip);
-
- return(lineCount);
- }
-
-